#pragma oce
#include<iostream>
#include<string>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<functional>
#include"Log.hpp"
#include"InetAddr.hpp"

enum 
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR
};
const static int defaultfd = -1;
using func_t = std::function<std::string(const std::string& ,bool &Yes)>;

class UdpServer
{
    public:
    UdpServer(uint16_t port,func_t func)
    :_sockfd(defaultfd)
    ,_port(port)
    ,_isrunning(false)
    ,_func(func)
    {}
    void InitSserver()
        {
            //创建套接字
            _sockfd = socket(AF_INET,SOCK_DGRAM,0);
            //判断是否成功
            if(_sockfd<0)
            {
                //失败
                //日志
                exit(SOCKET_ERROR);
            }
            //成功
            //日志
            // 填充sockaddr_in结构
            //设置服务器地址
            struct sockaddr_in local;
            bzero(&local,sizeof(local));//初始化
            local.sin_family = AF_INET;
            local.sin_port=htons(_port);//主机转网络
            local.sin_addr.s_addr = INADDR_ANY;
            //绑定套接字
            int n = bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
            if(n<0)//小于0失败
            {
                //日志
                exit(BIND_ERROR);
            }
            //成功日志

        }
        //启动
    void Start()
    {
        _isrunning = true;
        while (true)
        {
            char request[1024];
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd,request,sizeof(request)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                request[n] = 0;
                IneAddr addr(peer);
                // log
                bool Yes;
                std::string  response = _func(request,Yes);//请求 回调出去，在外面进行数据处理
                //将server收到的数据发送给对方
                sendto(_sockfd,response.c_str(),response.size(),0,(struct sockaddr*)&peer,len);
            }
        }
        _isrunning = false;
        
    }
    ~UdpServer()
    {}
    private:
    int _sockfd;
    uint16_t _port;
    bool _isrunning;
    //服务器设定回调，用来让上层进行注册业务的处理方法
     func_t _func;
};